<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>09_ES11-可选链的使用过程</title>
  <!-- 
  在 JavaScript 的 ES11（ECMAScript 2020）中，引入了一个非常有用的特性——可选链（Optional Chaining）。可选链允许开发者在访问对象的深层嵌套属性时，避免出现  `TypeError`  错误，从而简化代码的书写。
  一、可选链的定义
  可选链运算符（ `?.` ）用于安全地访问嵌套对象的属性。当访问的属性不存在时，不会抛出错误，而是返回  `undefined` 。

  二、语法
  可选链的基本语法如下：
  obj?.property
  obj?.[expression]
  obj?.method()
  -  `obj?.property` ：如果  `obj`  存在且不是  `null`  或  `undefined` ，则返回  `obj.property` ，否则返回  `undefined` 。
  -  `obj?.[expression]` ：如果  `obj`  存在且不是  `null`  或  `undefined` ，则返回  `obj[expression]` ，否则返回  `undefined` 。
  -  `obj?.method()` ：如果  `obj`  存在且不是  `null`  或  `undefined` ，则调用  `method`  方法，否则返回  `undefined` 。

  三、示例
   1. 访问嵌套属性
  const user = {
      name: '小明',
      address: {
          city: '北京',
          zip: '100000'
      }
  };

  const city = user.address?.city; // 输出: '北京'
  const country = user.address?.country; // 输出: undefined
  在这个例子中， `user.address?.country`  安全地访问了一个不存在的属性  `country` ，返回  `undefined` ，而不会抛出错误。

   2. 访问数组元素
  const users = [{ name: '小红' }, { name: '小蓝' }];

  const firstUserName = users[0]?.name; // 输出: '小红'
  const secondUserAge = users[1]?.age; // 输出: undefined
  这里， `users[1]?.age`  访问了第二个用户的  `age`  属性，如果该属性不存在，则返回  `undefined` 。

   3. 调用方法
  const obj = {
      getName() {
          return '小明';
      }
  };

  const name = obj.getName?.(); // 输出: '小明'
  const age = obj.getAge?.(); // 输出: undefined
  在这个例子中， `getAge`  方法不存在，因此调用  `obj.getAge?.()`  返回  `undefined` 。

   4. 结合其他操作

  可选链还可以与其他操作符结合使用，例如：
  const user = null;
  const userName = user?.name ?? '未提供'; // 输出: '未提供'
  在这个例子中，使用了空值合并运算符（ `??` ）来提供默认值。

  四、总结
  - 安全访问：可选链运算符（ `?.` ）提供了一种安全的方式来访问嵌套对象的属性，避免了在属性不存在时抛出的错误。
  - 简化代码：使用可选链可以减少对  `if`  语句的使用，使代码更加简洁和可读。
  - 与其他运算符结合：可选链可以与空值合并运算符（ `??` ）等其他运算符结合使用，进一步提高代码的灵活性。
  -->
</head>
<body>

  <script>
    const obj = {
      name: 'why',
      friend: {
        name: 'kobe',
        friend: {
          name: 'james',
          // running: function() {
          //   console.log("running~")
          // }
        }
      }
    }

    // 1.直接调用: 非常危险
    // obj.friend.running()

    // 2.if判断: 麻烦/不够简洁
    // if (obj.friend && obj.friend.running) {
    //   obj.friend.running()
    // }

    // 3.可选链的用法: ?.
    console.log(obj.friend.friend.name)
    console.log(obj?.friend?.friend?.name)
    obj?.friend?.running?.()
    console.log(obj?.friend?.running?.())
  </script>
  
</body>
</html>